package com.ruoyi.car.business.service.impl;


import com.github.pagehelper.PageHelper;
import com.ruoyi.car.business.domain.BpmnInfo;
import com.ruoyi.car.business.mapper.BpmnInfoMapper;
import com.ruoyi.car.business.query.BpmnInfoQuery;
import com.ruoyi.car.business.service.IBpmnInfoService;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.file.FileUploadUtils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class BpmnInfoServiceImpl implements IBpmnInfoService {
    @Autowired
    private BpmnInfoMapper bpmnInfoMapper;

    @Autowired
    private RepositoryService repositoryService;

    @Override
    public List query(BpmnInfoQuery qo) {
        PageHelper.startPage(qo.getPageNum(),qo.getPageSize());
        return bpmnInfoMapper.selectForList();
    }

    @Override
    public String upload(MultipartFile file) throws IOException {
        // 通过工具类FileUploadUtils.getExtension的方法可以直接拿到后缀名称
        String extension = FileUploadUtils.getExtension(file);
        // 判断前端文件是否bpmn文件如果不是抛出异常
        if (!"bpmn".equalsIgnoreCase(extension)) {
            throw new ServiceException("只能上传bpmn格式文件");
        }
        // 若依提供了工具类FileUploadUtils可以直接实现文件的上传
        // upload获取到yml文件中配置的目录, 读取前端传入的file, 把file放入到yml文件配置的目录
        // 也可以在第三个参数 定义上传的文件, 但是只能抛出默认的提示 不能自定义提示, 第三参数的上传文件格式也有限制
        String filePath = FileUploadUtils.upload(RuoYiConfig.getProfile(), file);
        return filePath;
    }

    @Override
    public void deploy(String path, String bpmnType, String info) throws IOException {
        // 获取配置文件中的路径, 加上path找到对应的文件, 之前上传的文件
        File bpmn = new File(RuoYiConfig.getProfile(),path);
        FileInputStream inputStream = new FileInputStream(bpmn);
        // 进行部署操作
        // 1. 用仓库Service 创建deploy对象 相当于把文件部署到Activiti7中
        Deployment deploy = repositoryService.createDeployment()
                .addInputStream(path, inputStream)
                .deploy();
        // 释放资源
        inputStream.close();
        // 2. 获取流程定义对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploy.getId()) // 根据部署ID查到对应的流程定义ID
                .singleResult();
        // 3. 封装BpmnInfo的信息
        BpmnInfo bpmnInfo = new BpmnInfo();
        bpmnInfo.setBpmnName(bpmnInfoMapper.getByBpmnName(bpmnType));
        bpmnInfo.setDeployTime(new Date());
        bpmnInfo.setInfo(info);
        bpmnInfo.setBpmnType(bpmnType);
        bpmnInfo.setDeploymentId(deploy.getId());
        bpmnInfo.setActProcessId(processDefinition.getId());
        bpmnInfo.setActProcessKey(processDefinition.getKey());
        bpmnInfoMapper.insert(bpmnInfo);
    }

    @Override
    public InputStream getFileInputStream(String deploymentId, String type) {
        InputStream inputStream = null;
        // 获取流程定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .singleResult();
        if ("xml".equalsIgnoreCase(type)){
            String resourceName = processDefinition.getResourceName();
            // 使用仓库Service.getResourceAsStream获取到数据库的文件需要传入文件的部署ID 部署名称
            inputStream = repositoryService.getResourceAsStream(deploymentId,resourceName);
        }else {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
            DefaultProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
            inputStream = generator.generateDiagram(bpmnModel,
                    Collections.EMPTY_LIST,
                    Collections.EMPTY_LIST,
                    "宋体",
                    "宋体",
                    "宋体"
                    );
        }
        return inputStream;
    }

    @Override
    @Transactional
    public void delete(Long id) {
        // 根据传进来要删除的id获取bpmnInfo
        BpmnInfo bpmnInfo = bpmnInfoMapper.selectByPrimaryKey(id);
        // 获取deploymentId
        String deploymentId = bpmnInfo.getDeploymentId();
        // TODO 查询所有的流程实例, 找到业务标识, 更新业务标识信息
        // 删除BpmnInfo
        bpmnInfoMapper.deleteByPrimaryKey(id);
        // 删除部署文件
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .singleResult();
        // 删除流程定义
        repositoryService.deleteDeployment(deploymentId,true);
        String resourceName = processDefinition.getResourceName();
        //  构建File文件( 拿到文件目录加路径)
        File file = new File(RuoYiConfig.getProfile(),resourceName);
        if (file.exists()){
            file.delete();
        }
    }

    @Override
    public BpmnInfo getByBpmnType(String bpmnType) {
        return bpmnInfoMapper.getByBpmnType(bpmnType);
    }

    @Override
    public BpmnInfo get(Long bpmnInfoId) {
        return bpmnInfoMapper.selectByPrimaryKey(bpmnInfoId);
    }
}
